package com.yanqu.road.utils.monitor;

import com.alibaba.fastjson.JSON;
import com.yanqu.road.utils.executor.GameScheduledThreadPoolExecutor;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.mina.filter.executor.OrderedThreadPoolExecutor;

import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


public class MonitorHelper {
	protected final static Logger THREAD = LogManager.getLogger("THREAD");
	private static final Logger LOGGER = LogManager.getLogger(MonitorHelper.class.getName());

	public static ScheduledThreadPoolExecutor monitorExecutor;

	static {
		initMonitorExecutor();
		monitorFullGc();
	}

	public static void monitorPool(final String poolName, final ThreadPoolExecutor poolExecutor) {
		monitorExecutor.scheduleWithFixedDelay(new Runnable() {
			@Override
			public void run() {
				try {
					ThreadPoolInfo poolInfo = new ThreadPoolInfo(poolName, poolExecutor.getActiveCount(),
							poolExecutor.getPoolSize(),
							poolExecutor instanceof OrderedThreadPoolExecutor ? 0 : poolExecutor.getQueue().size(),
							poolExecutor.getTaskCount(), poolExecutor.getCompletedTaskCount());
					 LOGGER.info(JSON.toJSONString(poolInfo));
				} catch (Exception e) {
					LOGGER.error(e.getMessage(), e);
				}

			}
		}, 1000, 15000, TimeUnit.MILLISECONDS);
	}

	public static void monitorFullGc() {
		monitorExecutor.scheduleWithFixedDelay(new Runnable() {
			@Override
			public void run() {
				try {

				} catch (Exception e) {
					System.err.println(e.getMessage());
					LOGGER.error(e.getMessage(), e);
				}
			}
		}, 1000, 900, TimeUnit.SECONDS);
		monitorExecutor.scheduleWithFixedDelay(new FullGcMonitor(), 1, 1, TimeUnit.MINUTES);
	}

	private static void initMonitorExecutor() {
		monitorExecutor = new GameScheduledThreadPoolExecutor(1, new ThreadFactory() {
			private int threadIndex = 0;

			@Override
			public Thread newThread(Runnable runnable) {
				Thread thread = new Thread(runnable);
				thread.setDaemon(true);
				thread.setName("pool-monitor-" + threadIndex++);
				return thread;
			}
		});

		monitorPool("pool-monitor", monitorExecutor);
	}
}
